package com.gitee.magic.core.valid;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import com.gitee.magic.core.annotations.Column;
import com.gitee.magic.core.json.JsonArray;
import com.gitee.magic.core.json.JsonObject;
import com.gitee.magic.core.utils.CheckUtils;
import com.gitee.magic.core.utils.ReflectUtils;
import com.gitee.magic.core.utils.StringUtils;
import com.gitee.magic.core.valid.annotation.BooleanValid;
import com.gitee.magic.core.valid.annotation.Custom;
import com.gitee.magic.core.valid.annotation.Enum;
import com.gitee.magic.core.valid.annotation.Equals;
import com.gitee.magic.core.valid.annotation.Format;
import com.gitee.magic.core.valid.annotation.Length;
import com.gitee.magic.core.valid.annotation.NotEmpty;
import com.gitee.magic.core.valid.annotation.NotEquals;
import com.gitee.magic.core.valid.annotation.NotNull;
import com.gitee.magic.core.valid.annotation.Regex;
import com.gitee.magic.core.valid.annotation.TimeFormat;
import com.gitee.magic.core.valid.annotation.Format.FormatType;
import com.gitee.magic.core.valid.annotation.number.DoubleValid;
import com.gitee.magic.core.valid.annotation.number.FloatValid;
import com.gitee.magic.core.valid.annotation.number.IntegerValid;
import com.gitee.magic.core.valid.annotation.number.LongValid;
import com.gitee.magic.core.valid.annotation.number.ShortValid;

/**
 * @author start
 */
public class ValidContext {
	
	/**
	 * 验证字段类型
	 * 
	 * @param field
	 * @param value
	 */
	public static void verifyField(Field field, Object value) {
		if (field == null) {
			return;
		}
		String fieldName=field.getName();
		if(field.isAnnotationPresent(Column.class)) {
			Column column=field.getAnnotation(Column.class);
			fieldName=column.value();
		}
		verify(field.getAnnotation(NotNull.class),value,fieldName);
		verify(field.getAnnotation(NotEmpty.class),value,fieldName);
		verify(field.getAnnotation(Equals.class),value,fieldName);
		verify(field.getAnnotation(NotEquals.class),value,fieldName);
		verify(field.getAnnotation(Length.class),value,fieldName);
		verify(field.getAnnotation(ShortValid.class),value,fieldName);
		verify(field.getAnnotation(IntegerValid.class),value,fieldName);
		verify(field.getAnnotation(LongValid.class),value,fieldName);
		verify(field.getAnnotation(FloatValid.class),value,fieldName);
		verify(field.getAnnotation(DoubleValid.class),value,fieldName);
		verify(field.getAnnotation(Enum.class),field.getType(),value,fieldName);
		verify(field.getAnnotation(BooleanValid.class),value,fieldName);
		verify(field.getAnnotation(TimeFormat.class),value,fieldName);
		verify(field.getAnnotation(Format.class),value,fieldName);
		verify(field.getAnnotation(Regex.class),value,fieldName);
		verify(field.getAnnotation(Custom.class),value,fieldName);
	}
	
	/**
	 * 是否为null
	 * @param verify
	 * @param value
	 * @param fieldName
	 */
	public static void verify(NotNull verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if (value==null) {
			validException(verify.value(),fieldName,verify);
		}
	}
	
	/**
	 * 是否为空
	 * @param verify
	 * @param value
	 * @param fieldName
	 */
	public static void verify(NotEmpty verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		if ("".equals(String.valueOf(value))) {
			validException(verify.value(),fieldName,verify);
		}
	}
	
	/**
	 * 是否包含某值
	 * @param verify
	 * @param value
	 * @param fieldName
	 */
	public static void verify(Equals verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		List<String> items=Arrays.asList(verify.value());
		if(!items.contains(String.valueOf(value))) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	/**
	 * 是否不包含某值
	 * @param verify
	 * @param value
	 * @param fieldName
	 */
	public static void verify(NotEquals verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		List<String> items=Arrays.asList(verify.value());
		if(items.contains(String.valueOf(value))) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	/**
	 * 长度
	 * @param verify
	 * @param value
	 * @param fieldName
	 */
	public static void verify(Length verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		String val=String.valueOf(value);
		if (!(val.length() >= verify.min() && val.length() <= verify.max())) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	/**
	 * 短整型验证
	 * @param verify
	 * @param value
	 * @param fieldName
	 */
	public static void verify(ShortValid verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		Short val=null;
		try {
			val=Short.valueOf(String.valueOf(value));
		}catch(Exception e) {
			validException(verify.message(),fieldName,verify);
		}
		if (!(val >= verify.min() && val <= verify.max())) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	public static void verify(IntegerValid verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		Integer val=null;
		try {
			val=Integer.valueOf(String.valueOf(value));
		}catch(Exception e) {
			validException(verify.message(),fieldName,verify);
		}
		if (!(val >= verify.min() && val <= verify.max())) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	public static void verify(LongValid verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		Long val=null;
		try {
			val=Long.valueOf(String.valueOf(value));
		}catch(Exception e) {
			validException(verify.message(),fieldName,verify);
		}
		if (!(val >= verify.min() && val <= verify.max())) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	public static void verify(FloatValid verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		Float val=null;
		try {
			val=Float.valueOf(String.valueOf(value));
		}catch(Exception e) {
			validException(verify.message(),fieldName,verify);
		}
		if (!(val >= verify.min() && val <= verify.max())) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	public static void verify(DoubleValid verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		Double val=null;
		try {
			val=Double.valueOf(String.valueOf(value));
		}catch(Exception e) {
			validException(verify.message(),fieldName,verify);
		}
		if (!(val >= verify.min() && val <= verify.max())) {
			validException(verify.message(),fieldName,verify);
		}
	}
	
	public static void verify(BooleanValid verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		if(!CheckUtils.isBoolean(String.valueOf(value))){
			validException(verify.value(),fieldName,verify);
		}
	}
	
	/**
	 * 验证枚举类型
	 * @param verify
	 * @param type
	 * @param value
	 * @param fieldName
	 */
	public static void verify(Enum verify,Class<?> type,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		if (type.isEnum()) {
			String val=String.valueOf(value);
			for(Object e:type.getEnumConstants()) {
				if(String.valueOf(e).equals(val)) {
					return;
				}
			}
			validException(verify.value(),fieldName,verify);
		} else {
			validException(verify.value(),fieldName,verify);
		}
	}
	
	/**
	 * 验证时间日期格式
	 * @param value
	 */
	public static void verify(TimeFormat verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		if(!CheckUtils.checkTime(String.valueOf(value), verify.format())){
			validException(verify.message(),fieldName,verify);
		}
	}
	
	/**
	 * 验证数据格式
	 * @param value
	 */
	public static void verify(Format verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		if(verify.type()==FormatType.MOBILE){
			if(!CheckUtils.isMobile(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.PHONE){
			if(!CheckUtils.isPhone(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.MAIL){
			if(!CheckUtils.isMail(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.MD5){
			if(!CheckUtils.isMd5(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.BASE64){
			if(!CheckUtils.isBase64(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.SHA1){
			if(!CheckUtils.isSha1(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.IP){
			if(!CheckUtils.isIpAddress(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.MAC){
			if(!CheckUtils.isMacAddress(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.CHINESE){
			if(!CheckUtils.isChinese(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.BIT){
			if(!CheckUtils.isBit(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.BOOLEAN){
			if(!CheckUtils.isBoolean(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.SHORT){
			if(!CheckUtils.isShort(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.INTEGER){
			if(!CheckUtils.isInteger(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.LONG){
			if(!CheckUtils.isLong(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.FLOAT){
			if(!CheckUtils.isFloat(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.DOUBLE){
			if(!CheckUtils.isDouble(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.NUMBER){
			if(!CheckUtils.isNumber(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.DECIMAL){
			if(!CheckUtils.isDecimal(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.GE_ZERO){
			if(!StringUtils.geZeroNumber(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.GT_ZERO){
			if(!StringUtils.gtZeroNumber(String.valueOf(value))){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.JSONObject||
				verify.type()==FormatType.JSON_OBJECT){
			if(value.getClass().equals(String.class)) {
				value=new JsonObject(String.valueOf(value));
			}
			if(!CheckUtils.isJsonObject(value)){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.JSONArray||
				verify.type()==FormatType.JSON_ARRAY){
			if(value.getClass().equals(String.class)) {
				value=new JsonArray(String.valueOf(value));
			}
			if(!CheckUtils.isJsonArray(value)){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.JSONArrayLong||
				verify.type()==FormatType.JSON_ARRAY_LONG){
			if(value.getClass().equals(String.class)) {
				value=new JsonArray(String.valueOf(value));
			}
			if(!CheckUtils.isJsonArrayLong(value)){
				validException(verify.message(),fieldName,verify);
			}
		}else if(verify.type()==FormatType.IDCARD){
			String val=String.valueOf(value);
			if(!CheckUtils.isIdCard(val)){
				validException(verify.message(),fieldName,verify);
			}
		}
	}
	
	/**
	 * 验证正则表达式
	 * @param value
	 */
	public static void verify(Regex verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		if(!StringUtils.regex(String.valueOf(value), verify.regex())){
			validException(verify.message(),fieldName,verify);
		}
	}
	
	/**
	 * 自定义校验
	 * @param value
	 */
	public static void verify(Custom verify,Object value,String fieldName){
		if(verify==null){
			return;
		}
		if(value==null) {
			return;
		}
		ValidCheckCustom check=ReflectUtils.newInstance(verify.value());
		check.setParamName(verify,fieldName);
		if(!check.check(value)){
			validException(verify.message(),fieldName,verify);
		}
	}
	
	public static void validException(String verifyMessage,String fieldName,Annotation anno) {
		if(StringUtils.isEmpty(verifyMessage)) {
			String message=fieldName+" valid @"+anno.annotationType().getSimpleName()+" is error";
			throw new ValidException(message);
		}else {
			throw new ValidException(verifyMessage);
		}
	}
	
}
